package ansible

import (
	"fmt"
	"os"
	"strings"
)

type host struct {
	ipaddr, username, password string
	port                       int
	vars                       map[string]string
}

func (h *host) String() string {
	var tempVars []string
	for k, v := range h.vars {
		tempVars = append(tempVars, fmt.Sprintf("%s='%s'", k, v))
	}
	return fmt.Sprintf("%s    ansible_host=%s    ansible_user=%s    ansible_port=%d    ansible_password='%s'    %s\n", h.ipaddr, h.ipaddr, h.username, h.port, h.password, strings.Join(tempVars, "    "))
}

func newHost(ipaddr, username, password string, port int, vars map[string]string) *host {
	return &host{
		ipaddr:   ipaddr,
		username: username,
		password: password,
		port:     port,
		vars:     vars,
	}
}

type Inventory struct {
	Hosts   []*host
	tmpfile string
}

func (i *Inventory) String() string {
	var tempHosts []string
	for _, h := range i.Hosts {
		tempHosts = append(tempHosts, h.String())
	}
	return strings.Join(tempHosts, "\n")
}

func NewInventory() *Inventory {

	return &Inventory{
		Hosts: nil,
	}
}

func (i *Inventory) AddHost(ipaddr, username, password string, port int, vars map[string]string) *Inventory {
	i.Hosts = append(i.Hosts, newHost(ipaddr, username, password, port, vars))
	return i
}

func (i *Inventory) Bytes() []byte {
	return []byte(i.String())
}

func (i *Inventory) LocalStorage() (filename string, err error) {
	f, err := os.CreateTemp("", "ansible_playbook_*.yml")
	_, err = f.WriteString(i.String())
	if err != nil {
		return "", err
	}
	i.tmpfile = f.Name()
	return i.tmpfile, nil
}

func (i *Inventory) Close() error {
	if i.tmpfile != "" {
		if err := os.Remove(i.tmpfile); err != nil {
			return err
		}
	}
	return nil
}
